import os

from fastapi import APIRouter, Form, UploadFile, File, HTTPException
from pydantic import ValidationError
from starlette.responses import JSONResponse

from db.mysql_db import SessionDep
from models.image import Image
from models.product import Product
from schemas.product import ProductsResponse, ProductResponse

product = APIRouter(
    prefix="/products",
    tags=["products"],
    responses={404: {"description": "Not found"}},
)

UPLOAD_URL = "./static/images/product"
ALLOWED_EXTENSIONS = {"png", "jpg", "jpeg", "gif"}


def allowed_file(filename):
    return "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS


@product.post("/")
async def create_product(
        session: SessionDep,
        name: str = Form(...),
        price: float = Form(...),
        attribute: int = Form(...),
        file: UploadFile = File(...),
):
    try:
        new_product = Product(name=name, price=price, attribute=attribute)
    except ValidationError as e:
        raise JSONResponse(status_code=400, content={"error": e.errors()})

    session.add(new_product)
    session.commit()

    try:
        if not allowed_file(file.filename):
            session.rollback()
            raise HTTPException(status_code=400, detail="图片格式错误")

        os.makedirs(UPLOAD_URL, exist_ok=True)
        file_path = os.path.join(UPLOAD_URL, file.filename)
        with open(file_path, "wb") as f:
            f.write(file.file.read())

        image = Image(image_url=file_path, product_id=new_product.id, product=new_product)
        session.add(image)
        session.commit()
        new_product.image = image

        return JSONResponse(content={"message": "创建成功"}, status_code=200)
    except Exception as e:
        session.rollback()
        raise JSONResponse(status_code=400, content={"error": str(e)})


@product.get("/", response_model=ProductsResponse)
async def get_products(session: SessionDep, page: int, size: int, attribute: int | None = None):
    if attribute:
        db_products = session.query(Product).filter_by(attribute=attribute).offset((page - 1) * size).limit(size).all()
        total = session.query(Product).filter_by(attribute=attribute).count()
    else:
        db_products = session.query(Product).offset((page - 1) * size).limit(size).all()
        total = session.query(Product).count()

    products = []
    for product in db_products:
        products.append(ProductResponse.model_validate(product))
    return ProductsResponse(data=products, paging={"page": page, "size": size, "total": total})


@product.get("/{product_id}", response_model=ProductResponse)
async def get_product(session: SessionDep, product_id: int):
    product = session.query(Product).filter_by(id=product_id).first()
    if product is None:
        raise HTTPException(status_code=404, detail="产品不存在")
    return ProductResponse.model_validate(product)


@product.put("/{product_id}")
async def update_product(
        session: SessionDep,
        product_id: int,
        name: str = Form(...),
        price: float = Form(...),
        attribute: int = Form(...),
        file: UploadFile = File(None),
):
    product = session.query(Product).filter_by(id=product_id).first()
    if product is None:
        raise HTTPException(status_code=404, detail="产品不存在")
    product.name = name
    product.price = price
    product.attribute = attribute
    if file:
        if not allowed_file(file.filename):
            raise HTTPException(status_code=400, detail="图片格式错误")
        os.makedirs(UPLOAD_URL, exist_ok=True)
        file_path = os.path.join(UPLOAD_URL, file.filename)
        with open(file_path, "wb") as f:
            f.write(file.file.read())
        image = Image(image_url=file_path, product_id=product.id, product=product)
        session.add(image)
        session.commit()
        product.image = image
    session.add(product)
    session.commit()
    return JSONResponse(content={"message": "更新成功"}, status_code=200)


@product.delete("/{product_id}")
async def delete_product(session: SessionDep, product_id: int):
    product = session.query(Product).filter_by(id=product_id).first()
    if product is None:
        raise HTTPException(status_code=404, detail="产品不存在")
    session.delete(product)
    session.commit()
    return JSONResponse(content={"message": "删除成功"}, status_code=200)
